import { Plugin } from 'vite'
import fs from 'node:fs'
import path from 'node:path'
import ts from 'typescript'

interface Options {
    dirs: string // 输入目录
    dts: string // 输出的.d.ts文件路径
}

// 插件的配置
export default function myVitePlugin(options: Options): Plugin {
    const { dirs, dts } = options
    return {
        name: 'vite-plugin-i18n-types',
        enforce: 'pre', // 插件执行顺序
        transform(code, id) {
            if (!/\.ts$/.test(id)) return

            // 读取文件路径
            const inputPath = path.normalize(path.resolve(__dirname, '..', dirs))
            // 输出文件路径
            const outputPath = path.normalize(path.resolve(__dirname, '..', dts))

            if (path.normalize(id) !== inputPath) return
            const sourceCode = fs.readFileSync(inputPath, 'utf-8')

            // 解析 TypeScript 文件
            const sourceFile = ts.createSourceFile(inputPath, sourceCode, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS)

            const file = parseAndPrefixTSFile(sourceFile) as Record<string, any>

            // 生成dts
            const dtsFile = generateDTS(file, 'I18nSchemaType')
            writeFile(dtsFile, outputPath)
        },
    }
}

function parseAndPrefixTSFile(sourceFile: ts.SourceFile) {
    let exportDefaultObject: Record<string, any> | undefined

    function visitNode(node: ts.Node) {
        if (ts.isExportAssignment(node)) {
            if (ts.isObjectLiteralExpression(node.expression)) {
                const objectLiteral = node.expression
                exportDefaultObject = extractPropertiesFromObjectLiteral(objectLiteral)
            }
        }
        ts.forEachChild(node, visitNode)
    }

    visitNode(sourceFile)
    return exportDefaultObject
}

function extractPropertiesFromObjectLiteral(node: ts.ObjectLiteralExpression): Record<string, any> {
    const properties: Record<string, any> = {}

    node.properties.forEach((prop) => {
        if (ts.isPropertyAssignment(prop)) {
            const key = ts.isIdentifier(prop.name) ? prop.name.text : ''
            const value = prop.initializer
            if (key !== '') {
                if (ts.isObjectLiteralExpression(value)) {
                    properties[key] = extractPropertiesFromObjectLiteral(value)
                } else {
                    properties[key] = ts.isStringLiteral(value) || ts.isNumericLiteral(value) ? value.text : value
                }
            }
        }
    })

    return properties
}

function generateDTS(obj: Record<string, any>, typeName: string): string {
    const content: string[] = []
    for (const key1 in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key1)) {
            const value = obj[key1]
            const prefix = key1
            if (typeof value === 'object') {
                for (const key2 in value) {
                    if (Object.prototype.hasOwnProperty.call(value, key2)) {
                        content.push(`'${prefix}.${key2}':string`)
                    }
                }
            }
        }
    }
    return `declare global {\nexport type ${typeName} = {\n${content.join('\n')}\n}\n}`
}
function writeFile(dtsFile: string, outputPath: string) {
    // // 创建输出目录（如果不存在）
    const outputDir = path.dirname(outputPath)
    if (!fs.existsSync(outputDir)) {
        fs.mkdirSync(outputDir, { recursive: true })
    }
    // 写入文件
    fs.writeFileSync(outputPath, dtsFile)
}
